#pragma once

class Renderbuffer {

	friend class Engine;

private:

	static const GLenum drawBuffersData[3];
	
	GLuint diffuseTexture;
	
	GLuint normalTexture;
	
	GLuint positionTexture;
	
	GLuint depthTexture;

	GLuint framebuffer = 0;

	GLsizei width = 640;
	
	GLsizei height = 480;
	
	void resize(GLsizei width, GLsizei height);
	
	void bind();

public:

	const GLsizei getWidth() const;
	
	const GLsizei getHeight() const;
	
	Renderbuffer();
	
	~Renderbuffer();
	
};

void Renderbuffer::bind(){
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER,framebuffer);
	glDrawBuffers(3,drawBuffersData);
}

const GLsizei Renderbuffer::getWidth() const{
	return width;
}

const GLsizei Renderbuffer::getHeight() const{
	return height;
}

void Renderbuffer::resize(GLsizei width, GLsizei height){
	Renderbuffer::width = width;
	Renderbuffer::height = height;
	// сохраняем текущий фреймбуфер
	GLint sFramebuffer;
	glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING,&sFramebuffer);
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER,framebuffer);
	// изменяем размер текстур
	// diffuse (textures[0])
	glBindTexture(GL_TEXTURE_2D,diffuseTexture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,0);
	glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,diffuseTexture,0);
	// normal (textures[1])
	glBindTexture(GL_TEXTURE_2D,normalTexture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,0);
	glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,normalTexture,0);
	// position (textures[2])
	glBindTexture(GL_TEXTURE_2D,positionTexture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,0);
	glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT2,positionTexture,0);
	// depth (depthTexture)
	glBindTexture(GL_TEXTURE_2D,depthTexture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT,0);
	glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,depthTexture,0);
	// Востанавливаем фреймбуфер
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER,sFramebuffer);		
}

Renderbuffer::Renderbuffer(){
	glGenFramebuffers(1,&framebuffer);
	// diffuseTexture
	glGenTextures(1,&diffuseTexture);
	glBindTexture(GL_TEXTURE_2D,diffuseTexture);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_MODE,GL_NONE);
	// normalTexture
	glGenTextures(1,&normalTexture);
	glBindTexture(GL_TEXTURE_2D,normalTexture);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_MODE,GL_NONE);
	// positionTexture
	glGenTextures(1,&positionTexture);
	glBindTexture(GL_TEXTURE_2D,positionTexture);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_MODE,GL_NONE);
	
	// depthTexture
	glGenTextures(1,&depthTexture);
	glBindTexture(GL_TEXTURE_2D,depthTexture);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_MODE,GL_NONE);
	// resize framebuffer and textures
	resize(width, height);
}
	
Renderbuffer::~Renderbuffer(){
	glDeleteTextures(1,&diffuseTexture);
	glDeleteTextures(1,&normalTexture);
	glDeleteTextures(1,&positionTexture);
	glDeleteTextures(1,&depthTexture);
	glDeleteFramebuffers(1,&framebuffer);
}

const GLenum Renderbuffer::drawBuffersData[3] = {
	GL_COLOR_ATTACHMENT0,
	GL_COLOR_ATTACHMENT1,
	GL_COLOR_ATTACHMENT2		
};
